package com.sise.parkinglot.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sise.parkinglot.bean.CodeMsg;
import com.sise.parkinglot.bean.WeChatSession;
import com.sise.parkinglot.composition.PublicService;
import com.sise.parkinglot.entity.*;
import com.sise.parkinglot.mapper.*;
import com.sise.parkinglot.service.IUserService;
import com.sise.parkinglot.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ZJ
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private PublicService publicService;

    @Resource
    private IUserService userService;

    @Resource
    private ParkMapper parkMapper;

    @Resource
    private UserRecordMapper userRecordMapper;

    @Resource
    private RechargeMapper rechargeMapper;

    @Resource
    private VipLogMapper vipLogMapper;

    @Value("${wx.appid}")
    private String APPID;

    @Value("${wx.secret}")
    private String SECRET;

    @Override
    public CodeMsg<List<User>> queryUserList(Map<String, Object> map) {
        if (map.isEmpty()) {
            return new CodeMsg<List<User>>().setCode(400).setMsg("参数缺失");
        }
        Page<User> page = new Page<>((int) map.get("current"), (int) map.get("pageSize"));
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.lambda().select(User.class, info -> !info.getColumn().equals("password"));
        if (map.get("carId") != null && !map.get("carId").equals("")) {
            userQueryWrapper.eq("car_id", map.get("carId"));
        }
        if (map.get("openid") != null && !map.get("openid").equals("")) {
            userQueryWrapper.like("openid", map.get("openid"));
        }
        if (map.get("cardType") != null && !map.get("cardType").equals("")) {
            userQueryWrapper.eq("card_type", map.get("cardType"));
        }
        if (map.get("stationType") != null && !map.get("stationType").equals("")) {
            userQueryWrapper.eq("station_type", map.get("stationType"));
        }
        if (map.get("carNumber") != null && !map.get("carNumber").equals("")) {
            userQueryWrapper.like("car_number", map.get("carNumber"));
        }
        if (map.get("tel") != null && !map.get("tel").equals("")) {
            userQueryWrapper.like("tel", map.get("tel"));
        }
        if (map.get("nickName") != null && !map.get("nickName").equals("")) {
            userQueryWrapper.like("nick_name", map.get("nickName"));
        }
        if (map.get("gender") != null && !map.get("gender").equals("")) {
            userQueryWrapper.eq("gender", map.get("gender"));
        }
        if (map.get("parkingLot") != null && !map.get("parkingLot").equals("")) {
            userQueryWrapper.eq("parking_lot", map.get("parkingLot"));
        }
        if (map.get("state") != null && !map.get("state").equals("")) {
            userQueryWrapper.eq("state", map.get("state"));
        }
        if (map.get("createTime") != null && !map.get("createTime").equals("")) {
            userQueryWrapper.like("create_time", map.get("createTime"));
        }
        IPage<User> userPage = userMapper.selectPage(page, userQueryWrapper);
        List<User> userList = userPage.getRecords();
        return new CodeMsg<List<User>>().setCode(200).setMsg(String.valueOf(userPage.getTotal())).setData(userList);
    }

    @Override
    public CodeMsg<String> addUser(User user) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.lambda().eq(User::getTel, user.getTel());
        User getUser = userMapper.selectOne(userQueryWrapper);
        if (getUser != null) {
            return new CodeMsg<String>().setCode(400).setMsg("手机号已存在");
        }
        user.setPassword(publicService.md5Encryption(user.getPassword()));
        user.setCreateTime(LocalDateTime.now());
        int insert = userMapper.insert(user);
        if (insert == 1) {
            return new CodeMsg<String>().setCode(200).setMsg("添加成功");
        }
        return new CodeMsg<String>().setCode(401).setMsg("添加失败");
    }

    @Override
    public CodeMsg<String> frozenUser(int[] carIds) {
        List<User> userList = new ArrayList<>();
        for (int id : carIds) {
            userList.add(new User().setCarId(id).setState(2));
        }
        if (userService.updateBatchById(userList)) {
            return new CodeMsg<String>().setCode(200).setMsg("冻结成功");
        }
        return new CodeMsg<String>().setCode(400).setMsg("冻结失败");
    }

    @Override
    public CodeMsg<String> removeUser(int[] carIds) {
        List<Integer> userList = new ArrayList<>();
        for (int id : carIds) {
            userList.add(id);
        }
        if (userService.removeByIds(userList)) {
            return new CodeMsg<String>().setCode(200).setMsg("删除成功");
        }
        return new CodeMsg<String>().setCode(400).setMsg("删除失败");
    }

    @Override
    public CodeMsg<String> thawUser(int[] carIds) {
        List<User> userList = new ArrayList<>();
        for (int id : carIds) {
            userList.add(new User().setCarId(id).setState(1));
        }
        if (userService.updateBatchById(userList)) {
            return new CodeMsg<String>().setCode(200).setMsg("解冻成功");
        }
        return new CodeMsg<String>().setCode(400).setMsg("解冻失败");
    }

    @Override
    public CodeMsg<String> updateUser(User user) {
        User getUser = userMapper.selectById(user.getCarId());
        if (getUser == null) {
            return new CodeMsg<String>().setCode(400).setMsg("用户不存在");
        }
        int update = userMapper.updateById(user);
        if (!getUser.getCardType().equals(user.getCardType())) {
            vipLogMapper.insert(new VipLog().setUserId(user.getCarId()).setVip(user.getCardType()).setUpdateTime(LocalDateTime.now()));
        }
        if (update == 1) {
            return new CodeMsg<String>().setCode(200).setMsg("编辑成功");
        }
        return new CodeMsg<String>().setCode(401).setMsg("编辑失败");
    }

    @Override
    public CodeMsg<String> upUser(Map<String, Object> map) {
        if (map.isEmpty()) {
            return new CodeMsg<String>().setCode(400).setMsg("参数缺失");
        }
        String id = publicService.getUserIdByToken(String.valueOf(map.get("token")));
        User user = userMapper.selectById(id);
        if (user != null) {
            user.setAvatarUrl((String) map.get("avatarUrl"))
                    .setNickName((String) map.get("nickName"))
                    .setGender((Integer) map.get("gender"));
            userMapper.updateById(user);
            userRecordMapper.insert(new UserRecord().setUserId(user.getCarId()).setMsg("更新用户微信数据").setRecordTime(LocalDateTime.now()));
            return new CodeMsg<String>().setCode(200).setMsg("更新成功");
        } else {
            return new CodeMsg<String>().setCode(401).setMsg("用户不存在");
        }
    }

    @Override
    public CodeMsg<String> updateUserByToken(Map<String, String> map) {
        if (map.isEmpty()) {
            return new CodeMsg<String>().setCode(400).setMsg("参数缺失");
        }
        User user = new User().setCarNumber(map.get("carNumber"))
                .setStationType(Integer.valueOf(map.get("stationType")))
                .setTel(map.get("tel"))
                .setCarId(Integer.valueOf(JwtUtil.verify(map.get("token")).getClaim("id").asString()));
        userRecordMapper.insert(new UserRecord().setUserId(user.getCarId()).setMsg("更新用户账号信息").setRecordTime(LocalDateTime.now()));
        int updateById = userMapper.updateById(user);
        if (updateById == 1) {
            return new CodeMsg<String>().setCode(200).setMsg("更新成功");
        }
        return new CodeMsg<String>().setCode(400).setMsg("更新失败");
    }

    @Override
    public CodeMsg<String> getToken(Map<String, Object> map) {
        if (map.isEmpty() || map.get("code") == null) {
            return new CodeMsg<String>().setCode(400).setMsg("参数缺失");
        }
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + APPID +
                "&secret=" + SECRET + "&js_code=" + map.get("code") + "&grant_type=authorization_code";
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, String.class);

        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            String sessionData = responseEntity.getBody();
            WeChatSession weChatSession = JSON.parseObject(sessionData, WeChatSession.class);
            assert weChatSession != null;
            String openId = weChatSession.getOpenid();
            if (openId.equals("")) {
                return new CodeMsg<String>().setCode(401).setMsg("获取信息失败，请稍后重试");
            }
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.lambda().eq(User::getOpenid, openId);
            User user = userMapper.selectOne(userQueryWrapper);
            if (user == null) {
                user = new User().setOpenid(openId).setCreateTime(LocalDateTime.now());
                userMapper.insert(user);
            }
            userRecordMapper.insert(new UserRecord().setUserId(user.getCarId()).setMsg("登陆").setRecordTime(LocalDateTime.now()));
            Map<String, String> setMap = new HashMap<>();
            setMap.put("id", String.valueOf(user.getCarId()));
            String token = JwtUtil.createToken(setMap);
            return new CodeMsg<String>().setCode(200).setMsg("获取成功").setData(token);
        } else {
            return new CodeMsg<String>().setCode(402).setMsg("请求微信服务器失败，请稍后重试");
        }
    }

    @Override
    public CodeMsg<String> addWalletUser(Map<String, String> map) {
        if (map.isEmpty()) {
            return new CodeMsg<String>().setCode(400).setMsg("参数缺失");
        }
        User user = userMapper.selectById(map.get("carId"));
        if (user == null) {
            return new CodeMsg<String>().setCode(401).setMsg("用户不存在");
        }
        BigDecimal overage = new BigDecimal(map.get("overage"));
        user.setOverage(user.getOverage().add(overage));
        Recharge recharge = new Recharge().setUserId(user.getCarId()).setSource(2).setRecharge(overage).setCreateTime(LocalDateTime.now());
        int i = userMapper.updateById(user);
        if (i == 1) {
            rechargeMapper.insert(recharge.setMsg("充值成功"));
            return new CodeMsg<String>().setCode(200).setMsg("充值成功");
        }
        rechargeMapper.insert(recharge.setMsg("充值失败"));
        return new CodeMsg<String>().setCode(402).setMsg("充值失败");
    }

    @Override
    public CodeMsg<String> getOverage(Map<String, String> map) {
        if (map.isEmpty()) {
            return new CodeMsg<String>().setCode(400).setMsg("参数缺失");
        }
        User user = userMapper.selectById(publicService.getUserIdByToken(map.get("token")));
        if (user == null) {
            return new CodeMsg<String>().setCode(401).setMsg("用户不存在");
        }
        if (user.getOverage() == null) {
            user.setOverage(BigDecimal.valueOf(0));
            userMapper.updateById(user);
        }
        return new CodeMsg<String>().setCode(200).setMsg("获取成功").setData(user.getOverage().toString());
    }

    @Override
    public CodeMsg<String> addOverage(Map<String, String> map) {
        if (map.isEmpty()) {
            return new CodeMsg<String>().setCode(400).setMsg("参数缺失");
        }
        if (map.get("overage") == null) {
            return new CodeMsg<String>().setCode(402).setMsg("未输入金额");
        }
        User user = userMapper.selectById(publicService.getUserIdByToken(map.get("token")));
        if (user == null) {
            return new CodeMsg<String>().setCode(401).setMsg("用户不存在");
        }
        BigDecimal overage = BigDecimal.valueOf(Float.parseFloat(map.get("overage")));
        user.setOverage(user.getOverage().add(overage));
        Recharge recharge = new Recharge().setUserId(user.getCarId()).setSource(1).setRecharge(overage).setCreateTime(LocalDateTime.now());
        int i = userMapper.updateById(user);
        if (i == 1) {
            rechargeMapper.insert(recharge.setMsg("充值成功"));
            return new CodeMsg<String>().setCode(200).setMsg("充值成功");
        }
        rechargeMapper.insert(recharge.setMsg("充值失败"));
        return new CodeMsg<String>().setCode(404).setMsg("充值失败");
    }

    @Override
    public CodeMsg<String> updateToken(Map<String, String> map) {
        if (map.isEmpty() || map.get("token") == null) {
            return new CodeMsg<String>().setCode(400).setMsg("参数缺失");
        }
        String id = publicService.getUserIdByToken(map.get("token"));
        Map<String, String> jwt = new HashMap<>();
        jwt.put("id", id);
        userRecordMapper.insert(new UserRecord().setUserId(Integer.valueOf(id)).setMsg("登陆小程序").setRecordTime(LocalDateTime.now()));
        return new CodeMsg<String>().setCode(200).setMsg("更新成功").setData(JwtUtil.createToken(jwt));
    }

    @Override
    public CodeMsg<User> getUserInfoByToken(Map<String, String> map) {
        if (map.isEmpty() || map.get("token") == null) {
            return new CodeMsg<User>().setCode(400).setMsg("参数缺失");
        }
        String id = publicService.getUserIdByToken(map.get("token"));
        User user = userMapper.selectById(id);
        if (user.getPassword() != null && !user.getPassword().equals("")) {
            user.setPassword("yes");
        } else {
            user.setPassword("no");
        }
        return new CodeMsg<User>().setCode(200).setMsg("获取成功").setData(user);
    }

    @Transactional
    @Override
    public CodeMsg<String> pay(Map<String, String> map) {
        if (map.isEmpty() || map.get("token") == null || map.get("password") == null) {
            return new CodeMsg<String>().setCode(400).setMsg("参数缺失");
        }
        String password = publicService.md5Encryption(map.get("password"));
        String id = publicService.getUserIdByToken(map.get("token"));
        User user = userMapper.selectById(id);
        if (user.getPassword() == null) {
            user.setPassword(password);
        } else {
            if (!user.getPassword().equals(password)) {
                userRecordMapper.insert(new UserRecord().setUserId(Integer.valueOf(id)).setMsg("支付密码错误").setRecordTime(LocalDateTime.now()));
                return new CodeMsg<String>().setCode(401).setMsg("支付密码错误");
            }
        }
        Park park = parkMapper.selectById(map.get("parkId"));
        if (park == null) {
            return new CodeMsg<String>().setCode(402).setMsg("订单不存在");
        }
        BigDecimal temp = user.getOverage().subtract(park.getFee());
        if (temp.compareTo(BigDecimal.ZERO) < 0) {
            userRecordMapper.insert(new UserRecord().setUserId(Integer.valueOf(id)).setMsg("金额不足").setRecordTime(LocalDateTime.now()));
            return new CodeMsg<String>().setCode(403).setMsg("金额不足");
        }

        // 如果停车记录支付成功并且未支付不超过5条，用户状态更改为正常状态
        if (user.getState() == 3){
            QueryWrapper<Park> getParkCount = new QueryWrapper<>();
            getParkCount.lambda().eq(Park::getCarId, user.getCarId()).eq(Park::getState, 1);
            final Integer integer = Math.toIntExact(parkMapper.selectCount(getParkCount));
            if (integer < 5){
                user.setState(1);
                userRecordMapper.insert(new UserRecord().setUserId(user.getCarId()).setMsg("用户缴费成功，账号激活").setRecordTime(LocalDateTime.now()));
            }
        }else{
            userRecordMapper.insert(new UserRecord().setUserId(Integer.valueOf(id)).setMsg("支付成功").setRecordTime(LocalDateTime.now()));
        }

        //更新信息
        user.setOverage(temp);
        park.setState(2);
        userMapper.updateById(user);
        parkMapper.updateById(park);
        return new CodeMsg<String>().setCode(200).setMsg("支付成功");
    }

    @Override
    public CodeMsg<String> updatePassword(Map<String, String> map) {
        if (map.isEmpty() || map.get("token") == null) {
            return new CodeMsg<String>().setCode(400).setMsg("参数缺失");
        }
        String id = publicService.getUserIdByToken(map.get("token"));
        String newPassword = publicService.md5Encryption(map.get("newPassword"));
        User user = userMapper.selectById(id);
        if (user.getPassword() == null || map.get("oldPassword") == null) {
            user.setPassword(newPassword);
        } else if (user.getPassword().equals(publicService.md5Encryption(map.get("oldPassword")))) {
            user.setPassword(newPassword);
        } else {
            userRecordMapper.insert(new UserRecord().setUserId(Integer.valueOf(id)).setMsg("旧密码不正确").setRecordTime(LocalDateTime.now()));
            return new CodeMsg<String>().setCode(401).setMsg("旧密码不正确");
        }
        int i = userMapper.updateById(user);
        if (i == 1) {
            userRecordMapper.insert(new UserRecord().setUserId(Integer.valueOf(id)).setMsg("密码修改成功").setRecordTime(LocalDateTime.now()));
            return new CodeMsg<String>().setCode(200).setMsg("修改成功");
        } else {
            userRecordMapper.insert(new UserRecord().setUserId(Integer.valueOf(id)).setMsg("密码修改失败").setRecordTime(LocalDateTime.now()));
            return new CodeMsg<String>().setCode(402).setMsg("修改失败");
        }
    }

}
